﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Vds2465Telegrams
{
    public class UserData_10_Query : UserData_Address
    {
        #region private member variables

        private readonly bool _simpleVariant = false;
        private readonly bool _generalVariant = false;
        private readonly bool _stateVariant = false;
        private readonly bool _testTimerVariant = false;

        private readonly byte _queryType;

        /// <summary>
        /// Used only in the general state query Variant
        /// </summary>
        private readonly byte _addressExtension = 0x00;

        /// <summary>
        /// Used only in the State Query Variant
        /// </summary>
        private readonly eAddressExtension_1 _addressExtension1;

        /// <summary>
        /// Used only in the Test Timer Variant
        /// </summary>
        private readonly eAddressExtension_2 _addressExtension2;

        #endregion private member variables

        #region constructor

        /// <summary>
        /// Simple variant, no further address data used
        /// </summary>
        /// <param name="queryType"></param>
        /// <param name="device"></param>
		public UserData_10_Query(byte queryType, byte device)
			: base(UserData.UserData10Query, device, 0x00, 0x00)
		{
            _queryType = queryType;

			_simpleVariant = true;

            if (
                   (queryType == UserData.UserData20State)
               || (queryType == UserData.UserData24BlockState)
                || (queryType == UserData.UserData41TestConfirm)
               )
            {
                // TODO: handle this error, remark: the above 3 values need more data, see the below constructor
            }                         
		}
               
        /// <summary>
        /// general state query variant - address and general address extension
        /// </summary>
        public UserData_10_Query(byte queryType, byte device, byte address, byte addressAddOn, byte addressExtension)
            : base(UserData.UserData10Query, device, address, addressAddOn)
        {
            _queryType = queryType;
            _addressExtension = addressExtension;

            if ((queryType == UserData.UserData20State)
                || (queryType == UserData.UserData24BlockState)
                )
            {
                _stateVariant = true;
                // TODO how handle if addressExtension has an invalid value?
                _addressExtension1 = (eAddressExtension_1)addressExtension;
            }
            else if (queryType == UserData.UserData41TestConfirm)
            {
                _testTimerVariant = true;
                // TODO how handle if addressExtension has an invalid value?
                _addressExtension2 = (eAddressExtension_2)addressExtension;
            }
            else
            {
                _generalVariant = true;_addressExtension = addressExtension;
            }
        }

		#endregion constructor

        #region getters

        public bool SimpleVariant { get { return _simpleVariant; } }
        public bool GeneralVariant { get { return _generalVariant; } }
        public bool StateVariant { get { return _stateVariant; } }
        public bool TestTimerVariant { get { return _testTimerVariant; } }

        public byte QueryType { get { return _queryType; } }

        public byte AddressExtension { get { return _addressExtension; } }
        public eAddressExtension_1 AddressExtension_1 { get { return _addressExtension1; } }
        public eAddressExtension_2 AddressExtension_2 { get { return _addressExtension2; } }

        #endregion getters

        #region ToString, Equals, GetHashCode

        public override int GetHashCode()
        {
            int hashCode = base.GetHashCode();

            hashCode ^= (SimpleVariant ? 1 : 0);
            hashCode ^= (GeneralVariant ? 1 : 0);
            hashCode ^= (StateVariant ? 1 : 0);
            hashCode ^= (TestTimerVariant ? 1 : 0);

            hashCode ^= QueryType;
            hashCode ^= AddressExtension;
            hashCode ^= (byte)AddressExtension_1;
            hashCode ^= (byte)AddressExtension_2;

            return hashCode;
        }

        public override string ToString()
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append("(");
            stringBuilder.Append(ToStringProperties());
            stringBuilder.Append(")");

            return stringBuilder.ToString();
        }

        internal override string ToStringProperties()
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append(base.ToStringProperties());

            stringBuilder.Append(", ");

            stringBuilder.Append("SimpleVariant='");
            stringBuilder.Append(SimpleVariant);
            stringBuilder.Append("'");

            stringBuilder.Append(", ");

            stringBuilder.Append("GeneralVariant='");
            stringBuilder.Append(GeneralVariant);
            stringBuilder.Append("'");

            stringBuilder.Append(", ");

            stringBuilder.Append("StateVariant='");
            stringBuilder.Append(StateVariant);
            stringBuilder.Append("'");

            stringBuilder.Append(", ");

            stringBuilder.Append("TestTimerVariant='");
            stringBuilder.Append(TestTimerVariant);
            stringBuilder.Append("'");

            stringBuilder.Append(", ");

            stringBuilder.Append("QueryType='");
            stringBuilder.Append(QueryType);
            stringBuilder.Append("'");

            stringBuilder.Append(", ");

            stringBuilder.Append("AddressExtension='");
            stringBuilder.Append(AddressExtension);
            stringBuilder.Append("'");

            stringBuilder.Append(", ");

            stringBuilder.Append("AddressExtension_1='");
            stringBuilder.Append(AddressExtension_1);
            stringBuilder.Append("'");

            stringBuilder.Append(", ");

            stringBuilder.Append("AddressExtension_2='");
            stringBuilder.Append(AddressExtension_2);
            stringBuilder.Append("'");

            return stringBuilder.ToString();
        }

        public override bool Equals(object obj)
        {
            Type objType = obj.GetType();
            if (this.GetType() == objType)
            {
                UserData_10_Query userData2Compare = obj as UserData_10_Query;
                return EqualsProperties(userData2Compare);
            }

            return false;
        }

        internal bool EqualsProperties(UserData_10_Query userData2Compare)
        {
            if (base.EqualsProperties(userData2Compare))
            {
                if (SimpleVariant == userData2Compare.SimpleVariant)
                {
                    if (GeneralVariant == userData2Compare.GeneralVariant)
                    {
                        if (StateVariant == userData2Compare.StateVariant)
                        {
                            if (TestTimerVariant == userData2Compare.TestTimerVariant)
                            {
                                if (QueryType == userData2Compare.QueryType)
                                {
                                    if (AddressExtension == userData2Compare.AddressExtension)
                                    {
                                        if (AddressExtension_1 == userData2Compare.AddressExtension_1)
                                        {
                                            return (AddressExtension_2 == userData2Compare.AddressExtension_2);
                                        }

                                        return false;
                                    }

                                    return false;
                                }

                                return false;
                            }

                            return false;
                        }

                        return false;
                    }

                    return false;
                }

                return false;
            }

            return false;
        }

        #endregion ToString, Equals, GetHashCode
    }
}
